package com.thread.auxiliaryClassUse;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * CyclicBarrier（循环屏障） 直译为可循环使⽤（Cyclic）的屏障（Barrier）。它可以让⼀组线程到达⼀个屏障（同步点）时被阻塞，直到
 * 最后⼀个线程到达屏障时，屏障才会开门，所有被屏障拦截的线程才会继续⼯作
 *
 * 可以被复用
 *
 * 应⽤场景： CyclicBarrier可以⽤于多线程计算数据，最后合并计算结果的应⽤场景。⽐如现在需要计算10个⼈12个⽉内的⼯资详细，可
 * 以将线程分为10个，分别计算每个⼈的⼯资，最后，再⽤barrierAction将这些线程的计算结果进⾏整合，得出最后结果。
 *
 * CountDownLatch与CyclicBarrier:
 * CountDownLatch是⼀个同步的辅助类，允许⼀个或多个线程，等待其他⼀组线程完成操作，再继续执⾏。
 * CyclicBarrier是⼀个同步的辅助类，允许⼀组线程相互之间等待，达到⼀个共同点，再继续执⾏。
*/
public class CyclicBarrierTest {

    public static void main(String[] args) {
        int parties = 4;
        // 参数parties指让多少个线程或者任务等待至barrier状态；参数barrierAction为当这些线程都达到barrier状态时会执行的内容。

        // 如果说想在所有线程写入操作完之后，没有额外操作；
        CyclicBarrier cb = new CyclicBarrier(parties);
        // 如果说想在所有线程写入操作完之后，进行额外的其他操作可以为CyclicBarrier提供Runnable参数：
        /*CyclicBarrier cb = new CyclicBarrier(parties, new Runnable() {
            @Override
            public void run() {
                System.out.println("当前线程是："+Thread.currentThread().getName());
            }
        });*/

        for (int i = 0; i < parties; i++) {
            new Writer(cb).start();
        }


        // CyclicBarrier重用
       /* try {
            Thread.sleep(25000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("CyclicBarrier重用");
        for(int i=0;i<parties;i++) {
            new Writer(cb).start();
        }*/
    }

    static class Writer extends Thread{
        private CyclicBarrier cyclicBarrier;
        public Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            System.out.println("线程"+Thread.currentThread().getName()+"正在写入数据...");
            try {
                Thread.sleep(5000); //以睡眠来模拟写入数据操作
                System.out.println("线程"+Thread.currentThread().getName()+"写入数据完毕，等待其他线程写入完毕");
                cyclicBarrier.await();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("所有线程写入完毕，继续处理其他任务...");
        }
    }

}
